#include <iostream>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <ctime>

// 非阻塞式IO
bool SetNonBlock(int fd)
{
    int fl = fcntl(fd, F_GETFL);  // 在底层获取当前fd对应的文件读写标志位
    if (fl < 0) return false;
    fcntl(fl, F_SETFL, fl | O_NONBLOCK);  // 设置非阻塞
    return true;
}

int main()
{
    // 这里不创建文件描述符了,以0号描述符为例 stdin
    SetNonBlock(0);
    char buffer[1024];
    while (true)
    {
        errno = 0;

        ssize_t s = read(0, buffer, sizeof(buffer) - 1);  // 出错的话,errno会被设置,表明出错原因
        // 读取成功返回读取到的位置,读取失败会重置errno
        // errno == EWOULDBLOCK || errno == EAGAIN  -> 代表没有数据就绪,再试一次 continue
        // errno == EINTR -> 被信号中断了
        // else  就是读取失败了
        if (s > 0)
        {
            buffer[s - 1] = 0;
            std::cout << "echo# " << buffer << " errno: " << errno << " errstring: " << strerror(errno) << std::endl;
        }
        else
        {
            // 如果读取失败errno的值为11,代表没有错,只是数据没有就绪
            std::cout << " errno: " << errno << " errstring: " << strerror(errno) << std::endl;

            if (errno == EWOULDBLOCK || errno == EAGAIN)
            {
                std::cout << "当前0号数据没有就绪, 请下一次再来试试" << std::endl;
                sleep(1);
                continue;
            }
            else if (errno == EINTR)
            {
                std::cout << "当前IO可能被信号中断,再试一下" << std::endl;
                sleep(1);
                continue;
            }
            else
            {
                // 出错了
                std::cout << "read \" error\"  " << " error: " << errno << " errstring: " << strerror(errno) << std::endl;
            }
            sleep(1);
        }
    }
    return 0;
}


// // 时间的接口
// #include <sys/time.h>
// int main()
// {
//     while (true)
//     {
//         std::cout << "time: " << (unsigned long)time(nullptr) << std::endl;
//         struct timeval curtime = {0, 0};
//         int n = gettimeofday(&curtime, nullptr);
//         if (n == -1)
//         {
//             std::cout << "gettimeofday error " << errno << ": " << strerror(errno) << std::endl;
//             exit(1);
//         }
//         (void)n;

//         std::cout << "gettimeofday: " << curtime.tv_sec << "." << curtime.tv_usec << std::endl;
//         sleep(1);
//     }

//     return 0;
// }
